package com.contract.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.contract.common.enums.RegisterTypeEnum;
import com.contract.common.enums.UserStateEnum;
import com.contract.common.error.BizException;
import com.contract.common.error.JsonReturnCode;
import com.contract.common.util.CommonUtil;
import com.contract.common.util.Constant;
import com.contract.common.util.HttpUtil;
import com.contract.common.util.JwtUtil;
import com.contract.mapper.SysRegisterMapper;
import com.contract.mapper.SysUserMapper;
import com.contract.pojo.bo.SysRegister;
import com.contract.pojo.bo.SysUser;
import com.contract.pojo.input.LoginInput;
import com.contract.pojo.output.JsonResult;
import com.contract.pojo.output.LoginOutput;
import com.contract.service.common.BaseService;
import com.contract.service.common.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * 登录service
 *
 * @author liw
 * @version 1.0
 * @date 2022/6/13 11:10
 */
@Service
@Slf4j
public class LoginService extends BaseService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRegisterMapper sysRegisterMapper;

    public JsonResult<LoginOutput> login(LoginInput vo) {

        UsernamePasswordAuthenticationToken authenticationToken;
        if (CommonUtil.isEmpty(vo.getUserName())) {
            String openId = getOpenId(vo);
            //1.通过AuthenticationManager的authenticate方法来进行用户认证
             authenticationToken = new UsernamePasswordAuthenticationToken(openId, openId);
        } else {
            //1.通过AuthenticationManager的authenticate方法来进行用户认证
             authenticationToken = new UsernamePasswordAuthenticationToken(vo.getUserName(), vo.getPassword());
        }

       Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(authenticate)) {
            throw new BizException(JsonReturnCode.USET_ERR);
        }
        //2.使用userid生成token
        LoginOutput showVo = new LoginOutput();
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        showVo.setId(loginUser.getUser().getId());
        showVo.setToken(JwtUtil.createJWT(JSON.toJSONString(loginUser)));
        return JsonResult.success(showVo);
    }

    public JsonResult<Void> logout() {
        //登陆成功后，会将用户信息存入SecurityContextholder,所以可以从SecurityContextholder中获取用户信息
        SecurityContextHolder.clearContext();
        return JsonResult.success();
    }

    private String getOpenId(LoginInput vo) {
        // 接收前端参数
        String code = vo.getCode();  //code
        //需要拿客户端获得的code换取openId
        String url = String.format(Constant.WX_LOGIN_URL, Constant.APP_ID, Constant.SECRET, code);
        //调用微信api授权
        String data = HttpUtil.doGet(url);
        if (CommonUtil.isEmpty(data)) {
            throw new BizException(JsonReturnCode.USET_CHAT_ERR);
        }
        //解析返回的json字符串属性	类型	说明
        JSONObject jsonObject = JSON.parseObject(data);
        String openId = jsonObject.getString("openid");
        if (CommonUtil.isEmpty(openId)) {
            throw new BizException(JsonReturnCode.USET_CHAT_ERR);
        }
        LambdaQueryWrapper<SysRegister> qw = new LambdaQueryWrapper<>();
        qw.eq(SysRegister::getOpenId, openId);
        Integer count = sysRegisterMapper.selectCount(qw);
        if (count == null || count == 0) {
            SysRegister user = new SysRegister();
            user.setOpenId(openId);
            user.setPassword(passwordEncoder.encode(openId));
            user.setType(RegisterTypeEnum.U.getKey());
            sysRegisterMapper.insert(user);
        }
        return openId;
    }

}
